愉快的推式子吧(ノ≧∀≦)ノ!
设 $f_i$ 表示前 $i$ 根柱子完工后的最小代价。枚举一个小于 $i$ 的 $j$ ,表示为从 $j$ 向 $i$ 连了一座桥,中间的柱子当然全部推掉,计算一下就好:
*其中 $s$ 为 $w$ 的前缀和。
于是最终式子变成了 $y=kx+b$ 的形式,斜率优化!
但是……注意这个式子的 $k$ 不是单调递增的,并且 $x$ 也不是单调递增的!那么我们不能用朴素做法了,也不能用二分……难道用 $Splay$ ?(码量巨大) 。
不,用 $CDQ$ 分治。
对于一个 $i$ ,可能可以对 $i$ 做出贡献的只有所有小于 $i$ 的 $j$ 。为了保证 $x$ 单调我们先大力将原来的数组按照 $x$ 从小到大排个序,然后 $CDQ$ 的时候分左右两边,左边的所有元素在初始数组的位置都小于右边的左右元素,也就是说我们直接用左边元素对右边元素做出贡献。
同时这里也保证了左右两边的 $x$ 一定是单调上增的。
我们使用单调队列,扫一遍左边的元素,留下能做贡献的点(下凸壳上的点),这时候左边的所有元素可以保证 $x$ 和斜率都是单调上增的。
右边呢?因为直线的斜率是 $2x$ ,而右边的 $x$ 也是单调上增的,所以我们可以愉快的做朴素的单调队列了。
$CDQ$ 分治部分的代码:
1 | void CDQ(int l,int r) { |
最后因为存在 $0$ ,在计算斜率的时候需要特判一下。还需要注意一下 $long\ long$ 的问题,记得将 $f$ 数组初始化。
Code:
1 |
|
本文标题:【题解】 [CEOI2017]Building Bridges 斜率优化DP loj2483
文章作者:Qiuly
发布时间:2019年04月27日 - 00:00
最后更新:2019年04月29日 - 21:17
原始链接:http://qiulyblog.github.io/2019/04/27/[题解]loj2483/
许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。